#include "SkillLightning.h"
#include "../Supporting/Enums/EnumSkillType.h"
#include "../Cats/CatsManager.h"
#include "../Cats/BaseCat.h"
#include "../Map/GameMap.h"
#include "../Supporting/SoundLoader.h"
#include "../Supporting/Enums/EnumSoundType.h"

using namespace cocos2d;

//===== CONSTRUCTOR =====
SkillLightning::SkillLightning() : BaseSkill()
{
	_skillType = SKILL_LIGHTNING;
	_skillEffectHitSprite = NULL;

	_skillDamage = 2;
	_chargePointRequired = 2;
	RECT_BUFFER_RADIUS = 10;

	skillEffectActivated = false;
}
//===== DESTRUCTOR ======
SkillLightning::~SkillLightning()
{
}

/*
 * @function: loadSkill
 * @param: filename of the skill button image to load
 * @brief: Create and load the skill as a CCSprite
 * @result: All required data loaded into memory
 */
BaseSkill* SkillLightning::loadSkill(cocos2d::CCString filename)
{
	SkillLightning *skill = new SkillLightning();

	if( skill && skill->initWithFile(filename.getCString()) )
	{
		skill->setColor(ccc3(100,100,100));
		skill->autorelease();
		return skill;
	}

	CC_SAFE_DELETE(skill);
	return NULL;
}

/*
 * @brief: Get the customised skill effect rectangle bounding box
 * @return: CCRect with a customised bounding box
 */
CCRect SkillLightning::getSkillEffectRect()
{
	if( !_skillEffectSprite )
		return CCRectMake(0,0,0,0);

	return CCRectMake(_skillEffectSprite->getPosition().x - (_skillEffectSprite->getContentSize().width/2) + RECT_BUFFER_RADIUS,
			_skillEffectSprite->getPosition().y - _skillEffectSprite->getContentSize().height/2 - (30*this->getScale()),
			_skillEffectSprite->getContentSize().width - RECT_BUFFER_RADIUS *2,
			(_skillEffectSprite->getContentSize().height / 4));
}

/*
 * @brief: Activate skill when user tap on the button. When this is enabled, the next touch will trigger the skill effect
 */
void SkillLightning::activateSkill()
{
	skillEffectActivated = true;
}

/*
 * @brief: Touch began funcion
 * @param location: location of the touch
 * @param mygamemanager: reference to GameManager
 * @return: true if this is a skill touch, else false
 */
bool SkillLightning::touchesBegan(cocos2d::CCPoint location, GameManager* mygamemanager)
{
	if( skillEffectActivated )
	{
		// Lightning Sound
		SoundLoader::playSound(SKILL_LIGHTNING_SOUND);

		//Get the y position to display the tornado
		int skilleffectposition = location.y;

		GameMap *myMap = GameMap::getInstance();
		int upperbound = myMap->getScreenTopBound()-(60*this->getScale());
		int lowerbound = myMap->getScreenBottomBound();

		//Capped it to the limits of the game screen
		if( location.y > upperbound )
			skilleffectposition = upperbound;
		else if( location.y < lowerbound )
			skilleffectposition = lowerbound;

		CCSize size = CCDirector::sharedDirector()->getWinSize();

		_skillEffectSprite = CCSprite::create();

		//========== ANIMATE IMAGE ==========
		CCAnimation *lightningFrames = CCAnimation::create();
		//load the frames of animation
		for( int j = 0 ; j < 7 ; j++ )
		{
			CCSpriteFrame *frame = CCSpriteFrame::create("Game/Skill/[VFX] Lightning (256).png", CCRect((j * 256), 0, 256, 384));
			lightningFrames->addSpriteFrame(frame);
		}

		//setup animation properties
		lightningFrames->setDelayPerUnit(0.1);
		lightningFrames->setRestoreOriginalFrame(false);
		CCAnimate *lightningAnimation = CCAnimate::create(lightningFrames);

		//start animating the running
		_skillEffectSprite->runAction(lightningAnimation);
		_skillEffectSprite->setScale(this->getScale());
		_skillEffectSprite->setPosition(ccp(location.x,skilleffectposition+(140*this->getScale())));
		this->getParent()->addChild(_skillEffectSprite,7);

		CCAnimation *lightningHitFrames = CCAnimation::create();
		//load the frames of animation
		for( int j = 0 ; j < 6 ; j++ )
		{
			CCSpriteFrame *frame = CCSpriteFrame::create("Game/Skill/[VFX] Lightning Hit (256).png", CCRect((j * 256), 0, 256, 256));
			lightningHitFrames->addSpriteFrame(frame);
		}
		//setup animation properties
		lightningHitFrames->setDelayPerUnit(0.1);
		lightningHitFrames->setRestoreOriginalFrame(false);
		CCAnimate *lightningHitAnimation = CCAnimate::create(lightningHitFrames);

		_skillEffectHitSprite = CCSprite::create();
		//start animating the running
		_skillEffectHitSprite->runAction(lightningHitAnimation);
		_skillEffectHitSprite->setScale(this->getScale()/1.5);
		_skillEffectHitSprite->setPosition(ccp(_skillEffectSprite->getPositionX(),
				(_skillEffectSprite->getPositionY()-150*this->getScale())));
		this->getParent()->addChild(_skillEffectHitSprite,7);

		skillEffectActivated = false;
		timeTaken = 0;

		return true;
	}
	else
		BaseSkill::touchesBegan(location,mygamemanager);
}

/*
 * @function: update
 * @brief: update loop function of the game
 * @param timeDiff: time difference between this loop and previous loop in seconds
 * @param pCatsRef: reference to MyCatsManager
 * @param chargepoint: chargepoints of the user
 * @result: execute game logic for lightning skill
 */
void SkillLightning::update(float timeDiff, CatsManager* pCatsRef, int chargepoints)
{
	//If skill effect is enabled
	if( _skillEffectSprite )
	{
		timeTaken += timeDiff;
		//Duration of the lightning
		if( timeTaken >= 0.7 )
		{
			_skillEffectSprite->removeFromParentAndCleanup(true);
			_skillEffectSprite = NULL;

			_isSkillActivated = false;

			//Enable the button is user has sufficient charge points
			if( chargepoints >= _chargePointRequired )
				this->setColor(ccc3(255,255,255));
		}
	}
	//For the hit area of the lightning, only apply damage here
	if( _skillEffectHitSprite )
	{
		if( timeTaken >= 0.6 )
		{
			_skillEffectHitSprite->removeFromParentAndCleanup(true);
			_skillEffectHitSprite = NULL;

			return;
		}

		CCArray *_cats = pCatsRef->returnCats();
		for( int i = 0 ; i < _cats->count() ; i++ )
		{
			BaseCat *cat = (BaseCat*)_cats->objectAtIndex(i);

			if (cat == NULL)
				continue;

			if(_skillEffectHitSprite->boundingBox().intersectsRect(cat->getRect()) )
				cat->reduceHealth(_skillDamage, INJURY_ZAPPED);
		}
	}
}
